package com.mapforge.map.tools.tilewriting;

import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Iterator;

import com.mapforge.Constants;
import com.mapforge.map.tilewriter.TileWriter;
import com.mapforge.map.tools.undo.CompositeUndoRedo;
import com.mapforge.map.tools.undo.tilelayeredit.PencilEdit;
import com.mapforge.selection.ContinuousSelection;
import com.mapforge.selection.Selection;
import com.mapforge.selection.TileSelection;

/** */
public class PencilTool extends AbstractTileWriterTool {

	private CompositeUndoRedo compositeUndoRedo;
	private Rectangle MAP_BOUNDS;

	public PencilTool() {
		super("Pencil tool");
		MAP_BOUNDS = new Rectangle();
	}

	/**
	 * Writes all tiles within the selection to the underlying layer.
	 */
	public void performEdit() {
		this.makeSelection();
		// construct edit and add to composite edit
		TileWriterToolState toolState = (TileWriterToolState) this.getState();
		PencilEdit edit = new PencilEdit(toolState, getTileLayer(), this
				.getCurrentSelection(), this);
		compositeUndoRedo.addEdit(edit);
		Selection destination = this.getCurrentSelection();
		System.out.println("PencilTool: Destination bounding rect = "
				+ destination.getBoundingRectangle());
		if (!destination.isEmpty()) {
			TileWriter tileWriter = getTileWriter();
			tileWriter.beginWrite();
			tileWriter.writeTiles(getTileSelection(), destination);
			tileWriter.endWrite();
		}
	}

	@Override
	public void beginEdit() {
		super.beginEdit();
		// initialize composite undo/redo if null
		if (compositeUndoRedo == null) {
			compositeUndoRedo = new CompositeUndoRedo(Constants.PENCIL_ICON,
					"Pencil");
		}
		performEdit();
	}

	public void endEdit() {
		super.endEdit();
		// TODO fire the composite edit to interested listeners.
	}

	/*
	 * private void hiddenPerformEdit() { this.verifyValidLayer(); // initialize
	 * composite undo/redo if null if (compositeUndoRedo == null) {
	 * compositeUndoRedo = new CompositeUndoRedo(Constants.PENCIL_ICON,
	 * "Pencil"); } // construct edit and add to composite edit
	 * TileWriterToolState toolState = (TileWriterToolState) this.getState();
	 * PencilEdit edit = new PencilEdit(toolState, getTileLayer(),
	 * getTileSelection(), this); compositeUndoRedo.addEdit(edit);
	 * this.makeSelection(); Selection destination = this.getCurrentSelection();
	 * System.out.println("PencilTool: Destination bounding rect = " +
	 * destination.getBoundingRectangle());
	 * this.getTileWriter().writeTiles(getTileSelection(), destination); //
	 * Selection destination = getToolSelection(this.getAnchorPoint(), //
	 * getMovingPoint(), this.getTileSelection()); //
	 * this.getTileWriter().writeTiles(getTileSelection(), destination); }
	 */

	/**
	 * Returns a selection of a rectangle defined by the users starting and
	 * ending drag points. The pencil tool writes immediately whenever its
	 * dragged to new points, so starting and current points should be the same.
	 */
	public Selection getToolSelection(Point startingPoint, Point currentPoint,
			Selection tileSelection) {
		Iterator<? extends Point> it = tileSelection.iterator();
		if (it.hasNext()) {
			MAP_BOUNDS.setFrame(0, 0, this.getTileMap()
					.getTotalHorizontalTiles(), getTileMap()
					.getTotalVerticalTiles());
			Rectangle r = tileSelection.getBoundingRectangle();
			r = (Rectangle) r.clone();
			r.setLocation(currentPoint);
			r = r.intersection(MAP_BOUNDS);
			System.out.println("PencilTool: MapBounds = " + MAP_BOUNDS + " "
					+ r);
			if (!r.isEmpty()) {
				return new ContinuousSelection(r);
			} else {
				return new ContinuousSelection();
			}
		} else {
			throw new IllegalArgumentException(
					"Tile selection cannot be empty.");
		}
	}

	/*
	 * @Override public void setMovingPoint(Point point) { if (point.x !=
	 * getMovingPoint().x || point.y != getMovingPoint().y) {
	 * super.setMovingPoint(point); hiddenPerformEdit(); } else {
	 * super.setMovingPoint(point); } }
	 */

	@Override
	public void paintTilePreview(Graphics2D g, Point startingPoint,
			Point currentPoint, Selection clipSelection,
			TileSelection tileSelection) {
		// intentionally left blank. No preview with pencil tool
	}

	@Override
	public Selection performSelection(Point startPoint, Point currentPoint) {
		this.validateState();
		return this.getToolSelection(startPoint, currentPoint,
				getTileSelection());
	}
}
